#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

using namespace std;

class udpClient
{
public:
    udpClient(string& serverIp, uint16_t serverPort)
    : _serverIp(serverIp),
      _serverPort(serverPort),
      _sockfd(-1)
    {}

    void initClient()
    {
        //创建socket
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd == -1)
        {
            cerr << strerror(errno) << endl;
            exit(1);
        }
        cerr << "create socket success " << _sockfd << endl;
       /*
       由os在调用sendto的时候自动绑定ip和port
       客户端无需手动绑定端口 因为指定的端口可能被客户端其他进程占用 由os自动分配未被占用的端口
       */
    }

    static void* recvMessage(void* args)
    {
        int sockfd = *(static_cast<int *>(args));
        pthread_detach(pthread_self());
        while (true)
        {
            char buffer[1024];
            struct sockaddr_in temp;
            socklen_t temp_len = sizeof(temp);
            size_t n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&temp, &temp_len);
            if (n > 0)
                buffer[n] = 0;
            cout << buffer << endl;
        }
        return nullptr;
    }

    //发送数据
    void start()
    {
        pthread_create(&_reader, nullptr, recvMessage, (void*)&_sockfd);
        struct sockaddr_in server;
        memset(&server, 0, sizeof server);
        server.sin_family = AF_INET;
        server.sin_port = htons(_serverPort);
        server.sin_addr.s_addr = inet_addr(_serverIp.c_str());
        string message;
        while (true)
        {
            fprintf(stderr, "please input# ");//等待cat读走管道的数据才能继续向管道里写入
            fflush(stderr);
            //cin >> message;//cin输入会以空格结尾
            getline(cin, message);
            //发什么 发多少 发给谁
            sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&server, sizeof server);
            //不用判断是否发送失败 发送失败再发就行了
            // char buffer[1024];
            // socklen_t server_len = sizeof server;
            // int n = recvfrom(_sockfd, buffer, sizeof buffer - 1, 0, (struct sockaddr*)&server, &server_len);
            // if (n >= 0)
            // {
            //     buffer[n] = 0;
            //     string response_message = buffer;
            //     //cout << "服务器翻译# " << response_message << endl;//demo1
            //     cout << response_message << endl;//demo2
            // }
        }
    }

private:
    string _serverIp;
    uint16_t _serverPort;
    int _sockfd;
    pthread_t _reader;
};